#include "atch_udp.h"

void destroy_udp_server(SocketUdpServer **sus)
{
    if (*sus == NULL)
    {
        printf("destroy udp server is null\n");
        return;
    }
    free(*sus);
    *sus = NULL;
}
void *udp_server_listen(void *parameter)
{
    SocketUdpServer *sus = (SocketUdpServer *)parameter;
    sus->serverfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (bind(sus->serverfd, (struct sockaddr *)&sus->serverAddr, sus->serverAddrLen) < 0)
    {
        perror("usp server listen bind error");
        return NULL;
    }
    printf("udp server start listen\n");

    while (1)
    {
        sus->clientAddrLen = sizeof(sus->clientAddr);
        int n = recvfrom(sus->serverfd,
                         sus->buffer,
                         sizeof(sus->buffer) - 1,
                         0,
                         (struct sockaddr *)&sus->clientAddr,
                         &sus->clientAddrLen);

        if (n == 0)
        {
            break;
        }
        else if (n < 0)
        {
            if (errno == EINTR)
                continue;
            if (errno == EAGAIN || errno == EWOULDBLOCK)
                continue;
            perror("read error");
            break;
        }
        else
        {
            sus->buffer[n] = '\0';
            if (sus->udpServerReceiveAction != NULL)
                sus->udpServerReceiveAction(sus);
        }
    }
    destroy_udp_server(&sus);
    return NULL;
}
SocketUdpServer *create_udp_server(int port, void (*susra)(SocketUdpServer *))
{
    SocketUdpServer *sus = (SocketUdpServer *)malloc(sizeof(SocketUdpServer));
    sus->port = htons(port);
    sus->serverAddr.sin_port = sus->port;
    sus->serverAddr.sin_family = AF_INET;
    sus->serverAddr.sin_addr.s_addr = INADDR_ANY;
    sus->udpServerReceiveAction = susra;
    sus->serverAddrLen = sizeof(sus->serverAddr);

    if (pthread_create(&sus->serverListenThread, NULL, udp_server_listen, sus) < 0)
    {
        destroy_udp_server(&sus);
        perror("create udp server error");
        return NULL;
    }
    return sus;
}
